package com.easylinkin.linkappapi.rulecomponent.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.deviceattribute.entity.DeviceAttribute;
import com.easylinkin.linkappapi.deviceattribute.mapper.DeviceAttributeMapper;
import com.easylinkin.linkappapi.deviceparm.entity.DeviceParm;
import com.easylinkin.linkappapi.deviceparm.mapper.DeviceParmMapper;
import com.easylinkin.linkappapi.deviceservice.entity.DeviceServices;
import com.easylinkin.linkappapi.deviceservice.mapper.DeviceServicesMapper;
import com.easylinkin.linkappapi.openapi.event.DeviceUnitVersionUpdateEvent;
import com.easylinkin.linkappapi.rulecomponent.entity.RuleComponent;
import com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentAttribute;
import com.easylinkin.linkappapi.rulecomponent.mapper.RuleComponentAttributeMapper;
import com.easylinkin.linkappapi.rulecomponent.mapper.RuleComponentMapper;
import com.easylinkin.linkappapi.rulecomponent.mapper.RuleComponentServiceMapper;
import com.easylinkin.linkappapi.rulecomponent.service.RuleComponentService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.tenant.entity.TenantRefDeviceUnit;

/**
 * <p>
 * 配电房 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2020-08-05
 */
@Service
public class RuleComponentServiceImpl extends ServiceImpl<RuleComponentMapper, RuleComponent> implements RuleComponentService {


    private static final Logger LOGGER = LoggerFactory.getLogger(RuleComponentServiceImpl.class);

    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    
    @Resource
    private RuleComponentMapper ruleComponentMapper;
    
    @Resource
    private RuleComponentAttributeMapper ruleComponentAttributeMapper;
    @Resource
    private RuleComponentServiceMapper ruleComponentServiceMapper;
    
	@Resource
	DeviceAttributeMapper deviceAttributeMapper;
	
	@Resource
	DeviceServicesMapper deviceServiceMapper;
	
	@Resource
	DeviceParmMapper deviceParmMapper;

	@Override
	@Transactional
	public void addRuleComponent(RuleComponent ruleComponent) {
		LinkappUser user = linkappUserContextProducer.getCurrent();
		commonService.setCreateAndModifyInfo(ruleComponent);
		ruleComponent.setTenantId(user.getTenantId());
		ruleComponentMapper.insert(ruleComponent);
		if("2".equalsIgnoreCase(ruleComponent.getType())) {
			List<RuleComponentAttribute> list = ruleComponent.getRuleComponentAttributes();
			if(list!=null) {
				for(RuleComponentAttribute ruleComponentAttribute : list) {
					ruleComponentAttribute.setRuleComponentId(ruleComponent.getId());
					ruleComponentAttribute.setTenantId(user.getTenantId());
					commonService.setCreateAndModifyInfo(ruleComponentAttribute);
					ruleComponentAttributeMapper.insert(ruleComponentAttribute);
				}
			}
		}
		if("3".equalsIgnoreCase(ruleComponent.getType())) {
			List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> list = ruleComponent.getRuleComponentServices();
			if(list!=null) {
				for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService ruleComponentService : list) {
					ruleComponentService.setRuleComponentId(ruleComponent.getId());
					String deviceServiceId = ruleComponentService.getId();
					List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> paramList = ruleComponentService.getParamList();
					for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService parm : paramList) {
						ruleComponentService.setDeviceServiceId(deviceServiceId);
						ruleComponentService.setId(null);
						ruleComponentService.setDeviceParmId(parm.getId());
						ruleComponentService.setUnit(parm.getUnit());
						ruleComponentService.setName(parm.getName());
						ruleComponentService.setSpecs(parm.getSpecs());
						ruleComponentService.setValue(parm.getValue());
						commonService.setCreateAndModifyInfo(ruleComponentService);
						ruleComponentService.setTenantId(user.getTenantId());
						ruleComponentServiceMapper.insert(ruleComponentService);
						if(parm.getChildParamList()!=null) {
							for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService childParam : parm.getChildParamList()) {
								com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService childRuleComponentService = new com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService();
								childRuleComponentService.setDeviceServiceId(deviceServiceId);
								childRuleComponentService.setDeviceParmId(childParam.getId());
								childRuleComponentService.setDeviceParmParentId(parm.getId());
								childRuleComponentService.setUnit(childParam.getUnit());
								childRuleComponentService.setName(childParam.getName());
								childRuleComponentService.setSpecs(childParam.getSpecs());
								childRuleComponentService.setValue(childParam.getValue());
								commonService.setCreateAndModifyInfo(childRuleComponentService);
								childRuleComponentService.setTenantId(user.getTenantId());
								childRuleComponentService.setRuleComponentId(ruleComponent.getId());
								ruleComponentServiceMapper.insert(childRuleComponentService);
							}
						}
					}
				}
			}
		}
	}
	
	@Override
	@Transactional
	public void deleteBatch(List<String> idList) {
		for(String id : idList) {
			RuleComponent ruleComponent = new RuleComponent();
			ruleComponent.setId(id);
			ruleComponent = ruleComponentMapper.getRuleComponent(ruleComponent);
			if("2".equalsIgnoreCase(ruleComponent.getType())) {
				Map<String,Object> map = new HashMap<String,Object>();
				map.put("rule_component_id", ruleComponent.getId());
				ruleComponentAttributeMapper.deleteByMap(map);
			}
			
			if("3".equalsIgnoreCase(ruleComponent.getType())) {
				Map<String,Object> map = new HashMap<String,Object>();
				map.put("rule_component_id", ruleComponent.getId());
				ruleComponentServiceMapper.deleteByMap(map);
			}
		}
		ruleComponentMapper.deleteBatchIds(idList);
		
		
		
	}
	
	@Override
	@Transactional
	public void updateRuleComponent(RuleComponent ruleComponent) {
		LinkappUser user = linkappUserContextProducer.getCurrent();
		ruleComponent.setTenantId(user.getTenantId());
		commonService.setModifyInfo(ruleComponent);
		ruleComponentMapper.updateById(ruleComponent);
		
		if("2".equalsIgnoreCase(ruleComponent.getType())) {
			List<RuleComponentAttribute> list = ruleComponent.getRuleComponentAttributes();
			if(list!=null) {
				Map<String,Object> map = new HashMap<String,Object>();
				map.put("rule_component_id", ruleComponent.getId());
				ruleComponentAttributeMapper.deleteByMap(map);
				for(RuleComponentAttribute ruleComponentAttribute : list) {
					ruleComponentAttribute.setRuleComponentId(ruleComponent.getId());
					commonService.setCreateAndModifyInfo(ruleComponentAttribute);
					ruleComponentAttributeMapper.insert(ruleComponentAttribute);
				}
			}
		}
		if("3".equalsIgnoreCase(ruleComponent.getType())) {
			List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> list = ruleComponent.getRuleComponentServices();
			if(list!=null) {
				Map<String,Object> map = new HashMap<String,Object>();
				map.put("rule_component_id", ruleComponent.getId());
				ruleComponentServiceMapper.deleteByMap(map);
				if(list!=null) {
					for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService ruleComponentService : list) {
						ruleComponentService.setRuleComponentId(ruleComponent.getId());
						String deviceServiceId = ruleComponentService.getId();
						List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> paramList = ruleComponentService.getParamList();
						for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService parm : paramList) {
							ruleComponentService.setDeviceServiceId(deviceServiceId);
							ruleComponentService.setId(null);
							ruleComponentService.setDeviceParmId(parm.getId());
							ruleComponentService.setUnit(parm.getUnit());
							ruleComponentService.setValue(parm.getValue());
							ruleComponentService.setName(parm.getName());
							ruleComponentService.setSpecs(parm.getSpecs());
							commonService.setCreateAndModifyInfo(ruleComponentService);
							ruleComponentService.setTenantId(user.getTenantId());
							ruleComponentServiceMapper.insert(ruleComponentService);
							
							if(parm.getChildParamList()!=null) {
								for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService childParam : parm.getChildParamList()) {
									com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService childRuleComponentService = new com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService();
									childRuleComponentService.setDeviceServiceId(ruleComponentService.getDeviceServiceId());
									childRuleComponentService.setDeviceParmId(childParam.getId());
									childRuleComponentService.setDeviceParmParentId(parm.getId());
									childRuleComponentService.setUnit(childParam.getUnit());
									childRuleComponentService.setValue(childParam.getValue());
									childRuleComponentService.setName(childParam.getName());
									childRuleComponentService.setSpecs(childParam.getSpecs());
									commonService.setCreateAndModifyInfo(childRuleComponentService);
									childRuleComponentService.setRuleComponentId(ruleComponent.getId());
									childRuleComponentService.setTenantId(user.getTenantId());
									ruleComponentServiceMapper.insert(childRuleComponentService);
								}
							}
						}
					}
				}
			}
		}
	}
	
	@Override
	public List<RuleComponent> getRuleComponents(RuleComponent ruleComponent) {
		return ruleComponentMapper.getRuleComponents(ruleComponent);
	}
	@Override
	public IPage<RuleComponent> getRuleComponents(Page page, RuleComponent ruleComponent) {
		
		if(ruleComponent.getType()!=null&&ruleComponent.getType().length()>0) {
			String[] types = ruleComponent.getType().split(",");
			ruleComponent.setTypes(types);
		}
		LinkappUser user = linkappUserContextProducer.getCurrent();
		ruleComponent.setTenantId(user.getTenantId());
		return ruleComponentMapper.getRuleComponents(page, ruleComponent);
	}
	@Override
	public RuleComponent getRuleComponent(RuleComponent ruleComponent) {
		LinkappUser user = linkappUserContextProducer.getCurrent();
		ruleComponent.setTenantId(user.getTenantId());
		ruleComponent = ruleComponentMapper.getRuleComponent(ruleComponent);
		if("2".equalsIgnoreCase(ruleComponent.getType())) {
			RuleComponentAttribute ruleComponentAttribute = new RuleComponentAttribute();
			ruleComponentAttribute.setRuleComponentId(ruleComponent.getId());
			
			List<RuleComponentAttribute> ruleComponentAttributes= ruleComponentAttributeMapper.getRuleComponentAttributes(ruleComponentAttribute);
			ruleComponent.setRuleComponentAttributes(ruleComponentAttributes);
		}
		if("3".equalsIgnoreCase(ruleComponent.getType())) {
			com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService ruleComponentService = new com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService();
			ruleComponentService.setRuleComponentId(ruleComponent.getId());
			
			List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> ruleComponentServices= ruleComponentServiceMapper.getRuleComponentServices(ruleComponentService);
			ruleComponent.setRuleComponentServices(ruleComponentServices);
		}
		return ruleComponent;
	}
	
	@Override
	public RuleComponent getRuleComponentById(String id) {
		RuleComponent ruleComponent = ruleComponentMapper.selectById(id);
		if("2".equalsIgnoreCase(ruleComponent.getType())) {
			RuleComponentAttribute ruleComponentAttribute = new RuleComponentAttribute();
			ruleComponentAttribute.setRuleComponentId(id);
			List<RuleComponentAttribute> ruleComponentAttributes= ruleComponentAttributeMapper.getRuleComponentAttributes(ruleComponentAttribute);
			ruleComponent.setRuleComponentAttributes(ruleComponentAttributes);
		}
		
		if("3".equalsIgnoreCase(ruleComponent.getType())) {
			com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService ruleComponentService = new com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService();
			ruleComponentService.setRuleComponentId(id);
			
			List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> ruleComponentServiceList = ruleComponentServiceMapper.getRuleComponentServiceList(ruleComponentService);
			List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> list = new ArrayList<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService>();
			for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService services : ruleComponentServiceList) {
				List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> ruleComponentServices = ruleComponentServiceMapper.getRuleComponentServices(services);
				services.setParamList(ruleComponentServices);
				list.add(services);
			}
			ruleComponent.setRuleComponentServices(list);
		}
		return ruleComponent;
	}
	
	@Async
	@EventListener
    public void onApplicationEvent(DeviceUnitVersionUpdateEvent deviceUnitVersionUpdateEvent) {
        Map<String, List<TenantRefDeviceUnit>>  message = (Map<String, List<TenantRefDeviceUnit>> ) deviceUnitVersionUpdateEvent.getSource();
        List<TenantRefDeviceUnit> tenantRefDeviceUnitAddList = message.get("add");
        List<TenantRefDeviceUnit> tenantRefDeviceUnitDeleteList = message.get("delete");
        Assert.notNull(tenantRefDeviceUnitAddList,"租户关联型号add列表为null");
        Assert.notNull(tenantRefDeviceUnitDeleteList,"租户关联型号delete列表为null");
        Set<String> actualAddedTenantRefDeviceUnitIds = new HashSet<>();
//        比较 add 和 delete 的找出 实际新增或修改的
        for (TenantRefDeviceUnit addTenantRefDeviceUnit : tenantRefDeviceUnitAddList) {
            for (TenantRefDeviceUnit deleteTenantRefDeviceUnit : tenantRefDeviceUnitDeleteList) {
                if (deleteTenantRefDeviceUnit.getTenantId().equals(addTenantRefDeviceUnit.getTenantId()) && deleteTenantRefDeviceUnit.getDeviceUnitId().equals(addTenantRefDeviceUnit.getDeviceUnitId())) {
                    break;
                }
                actualAddedTenantRefDeviceUnitIds.add(addTenantRefDeviceUnit.getDeviceUnitId());
            }
        }
        if(!actualAddedTenantRefDeviceUnitIds.isEmpty()) {
        	flushDeviceUnitDataDifferentFromTenantRefDeviceUnitGlobal(actualAddedTenantRefDeviceUnitIds,tenantRefDeviceUnitAddList.get(0).getTenantId());
        }
        LOGGER.info("接收到型号更新事件");
    }
	

	
	public void flushDeviceUnitDataDifferentFromTenantRefDeviceUnitGlobal(Set<String> actualAddedTenantRefDeviceUnitIds,String tenantId) {
		for(String deviceUnitId : actualAddedTenantRefDeviceUnitIds) {
			List<RuleComponentAttribute> ruleComponentAttributes = ruleComponentAttributeMapper.flushDeviceUnitData(deviceUnitId, tenantId);
			if(ruleComponentAttributes!=null && !ruleComponentAttributes.isEmpty()) {
				DeviceAttribute deviceAttributeQuery = new DeviceAttribute();
				deviceAttributeQuery.setDeviceUnitId(deviceUnitId);
				List<DeviceAttribute> deviceAttributes = deviceAttributeMapper.getAll(deviceAttributeQuery);
				//更新规则组件属性类别数据
				if(deviceAttributes!=null) {
					for(DeviceAttribute deviceAttribute : deviceAttributes) {
						for(RuleComponentAttribute ruleComponentAttribute : ruleComponentAttributes) {
							if(ruleComponentAttribute.getDeviceAttributeName().equalsIgnoreCase(deviceAttribute.getName())){
								ruleComponentAttribute.setDeviceAttributeId(deviceAttribute.getId());
								ruleComponentAttribute.setDeviceAttributeParentId(deviceAttribute.getParentId());
								ruleComponentAttributeMapper.updateById(ruleComponentAttribute);
							}
						}
					}
				}
			}
			
			
			List<com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService> ruleComponentServices = ruleComponentServiceMapper.flushDeviceUnitData(deviceUnitId, tenantId);
			DeviceServices deviceServiceQuery = new DeviceServices();
			deviceServiceQuery.setDeviceUnitId(deviceUnitId);
			List<DeviceServices> deviceServices = deviceServiceMapper.getDeviceServicesList(deviceServiceQuery);
			//更新规则组件服务类别数据
			if(ruleComponentServices!=null && !ruleComponentServices.isEmpty() && deviceServices!=null && !deviceServices.isEmpty()) {
				for(DeviceServices deviceService : deviceServices) {
					for(com.easylinkin.linkappapi.rulecomponent.entity.RuleComponentService ruleComponentService : ruleComponentServices) {
						if(ruleComponentService.getName().equalsIgnoreCase(deviceService.getName())){
							DeviceParm deviceParmQuery = new DeviceParm();
							deviceParmQuery.setDeviceServiceId(deviceService.getId());
							List<DeviceParm> deviceParms = deviceParmMapper.selectDeviceParmList(deviceParmQuery);
							if(deviceParms!=null) {
								for(DeviceParm deviceParm : deviceParms) {
									if(ruleComponentService.getDeviceParmName().equalsIgnoreCase(deviceParm.getName())) {
										ruleComponentService.setDeviceServiceId(deviceService.getId());
										ruleComponentService.setDeviceParmId(deviceParm.getId());
										ruleComponentService.setDeviceParmParentId(deviceParm.getParentId());
										ruleComponentService.setName(deviceParm.getName());
										ruleComponentService.setUnit(deviceParm.getUnit());
										ruleComponentService.setSpecs(deviceParm.getSpecs());
										ruleComponentServiceMapper.updateById(ruleComponentService);
									}
								}
							}
						}
					}
				}
			}
			
			
			
		}
	}
 
}
